﻿
namespace SistemaLogistica.DataAccess
{
    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Data.Common;
    using SistemaLogistica.Business.Entities;

    public class EmpleadoData : BaseDataAccess
    {
        private EmpleadoData() { }

        private readonly static EmpleadoData instancia = new EmpleadoData();

        public static EmpleadoData Instancia
        {
            get { return instancia; }
        }

        #region Empleados

        public List<Empleados> Listar()
        {
            List<Empleados> empleados = new List<Empleados>();
            DbCommand command = db.GetStoredProcCommand("GetAllFromEmpleados");

            using (IDataReader dr = db.ExecuteReader(command))
            {
                while (dr.Read())
                {
                    empleados.Add(new Empleados
                    {
                        Apellidos = dr.GetString(dr.GetOrdinal("Apellidos")),
                        Direccion = dr.GetString(dr.GetOrdinal("Direccion")),
                        DNI = dr.GetString(dr.GetOrdinal("DNI")),
                        Email = dr.GetString(dr.GetOrdinal("Email")),
                        IdEmpleado = dr.GetInt16(dr.GetOrdinal("IdEmpleado")),
                        Nombre = dr.GetString(dr.GetOrdinal("Nombre")),
                        Telefono = dr.GetString(dr.GetOrdinal("Telefono")),
                        Cargo = CargoData.Instancia.ObtenerPorID(dr.GetInt32(dr.GetOrdinal("IdCargo")))
                    });
                }
            }
            return empleados;
        }

        public Empleados ObtenerPorID(short idEmpleado)
        {
            Empleados empleado = null;
            DbCommand command = db.GetStoredProcCommand("GetEmpleadosByIdEmpleado");
            db.AddInParameter(command, "idEmpleado", DbType.Int16, idEmpleado);

            using (IDataReader dr = db.ExecuteReader(command))
            {
                while (dr.Read())
                {
                    empleado = new Empleados
                    {
                        Apellidos = dr.GetString(dr.GetOrdinal("Apellidos")),
                        Direccion = dr.GetString(dr.GetOrdinal("Direccion")),
                        DNI = dr.GetString(dr.GetOrdinal("DNI")),
                        Email = dr.GetString(dr.GetOrdinal("Email")),
                        IdEmpleado = dr.GetInt16(dr.GetOrdinal("IdEmpleado")),
                        Nombre = dr.GetString(dr.GetOrdinal("Nombre")),
                        Telefono = dr.GetString(dr.GetOrdinal("Telefono")),
                        Cargo = CargoData.Instancia.ObtenerPorID(dr.GetInt32(dr.GetOrdinal("IdCargo")))
                    };
                }
            }
            return empleado;
        }

        public List<Empleados> BuscarPorDNI(string dni)
        {
            List<Empleados> empleados = new List<Empleados>();
            DbCommand command = db.GetStoredProcCommand("GetEmpleadosByDNI");
            db.AddInParameter(command, "dni", DbType.String, dni);

            using (IDataReader dr = db.ExecuteReader(command))
            {
                while (dr.Read())
                {
                    empleados.Add(new Empleados
                    {
                        Apellidos = dr.GetString(dr.GetOrdinal("Apellidos")),
                        Direccion = dr.GetString(dr.GetOrdinal("Direccion")),
                        DNI = dr.GetString(dr.GetOrdinal("DNI")),
                        Email = dr.GetString(dr.GetOrdinal("Email")),
                        IdEmpleado = dr.GetInt16(dr.GetOrdinal("IdEmpleado")),
                        Nombre = dr.GetString(dr.GetOrdinal("Nombre")),
                        Telefono = dr.GetString(dr.GetOrdinal("Telefono")),
                        Cargo = CargoData.Instancia.ObtenerPorID(dr.GetInt32(dr.GetOrdinal("IdCargo")))
                    });
                }
            }
            return empleados;
        }

        public List<Empleados> BuscarPorNombre(string dni, string nombre, string apellidos)
        {
            List<Empleados> empleados = new List<Empleados>();
            DbCommand command = db.GetStoredProcCommand("GetEmpleadosByKeyWord");
            db.AddInParameter(command, "dni", DbType.String, dni);
            db.AddInParameter(command, "nombre", DbType.String, nombre);
            db.AddInParameter(command, "apellidos", DbType.String, apellidos);

            using (IDataReader dr = db.ExecuteReader(command))
            {
                while (dr.Read())
                {
                    empleados.Add(new Empleados
                    {
                        Apellidos = dr.GetString(dr.GetOrdinal("Apellidos")),
                        Direccion = dr.GetString(dr.GetOrdinal("Direccion")),
                        DNI = dr.GetString(dr.GetOrdinal("DNI")),
                        Email = dr.GetString(dr.GetOrdinal("Email")),
                        IdEmpleado = dr.GetInt16(dr.GetOrdinal("IdEmpleado")),
                        Nombre = dr.GetString(dr.GetOrdinal("Nombre")),
                        Telefono = dr.GetString(dr.GetOrdinal("Telefono")),
                        Cargo = CargoData.Instancia.ObtenerPorID(dr.GetInt32(dr.GetOrdinal("IdCargo")))
                    });
                }
            }
            return empleados;
        }

        public bool Agregar(Empleados empleado)
        {
            DbCommand command = db.GetStoredProcCommand("InsertEmpleados");
            db.AddInParameter(command, "apellidos", DbType.String, empleado.Apellidos);
            db.AddInParameter(command, "direccion", DbType.String, empleado.Direccion);
            db.AddInParameter(command, "dNI", DbType.String, empleado.DNI);
            db.AddInParameter(command, "email", DbType.String, empleado.Email);
            db.AddInParameter(command, "idCargo", DbType.Int32, empleado.Cargo.IdCargo);
            db.AddOutParameter(command, "idEmpleado", DbType.Int16, 11);
            db.AddInParameter(command, "nombre", DbType.String, empleado.Nombre);
            db.AddInParameter(command, "telefono", DbType.String, empleado.Telefono);

            int result = db.ExecuteNonQuery(command);

            if (result != 0) return true;
            else return false;
        }

        public bool Modificar(Empleados empleado)
        {
            DbCommand command = db.GetStoredProcCommand("UpdateEmpleados");
            db.AddInParameter(command, "apellidos", DbType.String, empleado.Apellidos);
            db.AddInParameter(command, "direccion", DbType.String, empleado.Direccion);
            db.AddInParameter(command, "dNI", DbType.String, empleado.DNI);
            db.AddInParameter(command, "email", DbType.String, empleado.Email);
            db.AddInParameter(command, "idCargo", DbType.Int32, empleado.Cargo.IdCargo);
            db.AddInParameter(command, "idEmpleado", DbType.Int16, empleado.IdEmpleado);
            db.AddInParameter(command, "nombre", DbType.String, empleado.Nombre);
            db.AddInParameter(command, "telefono", DbType.String, empleado.Telefono);

            int result = db.ExecuteNonQuery(command);

            if (result != 0) return true;
            else return false;
        }

        public void Eliminar(short idEmpleado)
        {
            DbCommand command = db.GetStoredProcCommand("DeleteEmpleados");
            db.AddInParameter(command, "idEmpleado", DbType.Int16, idEmpleado);
            db.ExecuteNonQuery(command);
        }

        #endregion

        #region Usuarios

        public List<Usuario> ListarUsuarios()
        {
            List<Usuario> usuarios = new List<Usuario>();
            DbCommand command = db.GetStoredProcCommand("GetAllFromUsuario");

            using (IDataReader dr = db.ExecuteReader(command))
            {
                while (dr.Read())
                {
                    Empleados empleado = ObtenerPorID(dr.GetInt16(dr.GetOrdinal("IdEmpleado")));
                    Usuario usuario = new Usuario
                    {
                        DNI = empleado.DNI,
                        Email = empleado.Email,
                        Nombre = empleado.Nombre,
                        Cargo = empleado.Cargo,
                        Apellidos = empleado.Apellidos,
                        Direccion = empleado.Direccion,
                        Telefono = empleado.Telefono,
                        EsAdministrador = dr.GetBoolean(dr.GetOrdinal("EsAdministrador")),
                        FechaRegistro = dr.GetDateTime(dr.GetOrdinal("FechaRegistro")),
                        IdEmpleado = dr.GetInt16(dr.GetOrdinal("IdEmpleado")),
                        Password = dr.GetString(dr.GetOrdinal("Password")),
                        Username = dr.GetString(dr.GetOrdinal("Username"))
                    };
                    usuarios.Add(usuario);
                }
            }
            return usuarios;
        }

        public Usuario ObtenerPorCredencial(string username, string password)
        {
            Usuario usuario = null;
            DbCommand command = db.GetStoredProcCommand("GetUsuarioByCredenciales");
            db.AddInParameter(command, "username", DbType.String, username);
            db.AddInParameter(command, "password", DbType.String, password);

            using (IDataReader dr = db.ExecuteReader(command))
            {
                while (dr.Read())
                {
                    Empleados empleado = ObtenerPorID(dr.GetInt16(dr.GetOrdinal("IdEmpleado")));
                    usuario = new Usuario
                    {
                        DNI = empleado.DNI,
                        Email = empleado.Email,
                        Nombre = empleado.Nombre,
                        Cargo = empleado.Cargo,
                        Apellidos = empleado.Apellidos,
                        Direccion = empleado.Direccion,
                        Telefono = empleado.Telefono,
                        EsAdministrador = dr.GetBoolean(dr.GetOrdinal("EsAdministrador")),
                        FechaRegistro = dr.GetDateTime(dr.GetOrdinal("FechaRegistro")),
                        IdEmpleado = dr.GetInt16(dr.GetOrdinal("IdEmpleado")),
                        Password = dr.GetString(dr.GetOrdinal("Password")),
                        Username = dr.GetString(dr.GetOrdinal("Username"))
                    };
                }
            }
            return usuario;
        }

        public void AgregarUsuario(Usuario usuario)
        {
            using (DbConnection conection = db.CreateConnection())
            {
                conection.Open();
                using (DbTransaction transaction = conection.BeginTransaction())
                {
                    try
                    {
                        DbCommand cmdUsuario = db.GetStoredProcCommand("InsertUsuario");

                        db.AddInParameter(cmdUsuario, "esAdministrador", DbType.Boolean, usuario.EsAdministrador);
                        db.AddInParameter(cmdUsuario, "fechaRegistro", DbType.DateTime, usuario.FechaRegistro);
                        db.AddInParameter(cmdUsuario, "idEmpleado", DbType.Int16, usuario.IdEmpleado);
                        db.AddInParameter(cmdUsuario, "password", DbType.String, usuario.Password);
                        db.AddInParameter(cmdUsuario, "username", DbType.String, usuario.Username);
                        db.ExecuteNonQuery(cmdUsuario, transaction);

                        DbCommand cmdPermisos = db.GetStoredProcCommand("InsertPermiso");
                        db.AddInParameter(cmdPermisos, "estado", DbType.Boolean);
                        db.AddInParameter(cmdPermisos, "idEmpleado", DbType.Int16);
                        db.AddInParameter(cmdPermisos, "idFormulario", DbType.Byte);
                        db.AddInParameter(cmdPermisos, "tipoPermiso", DbType.Byte);

                        foreach (Permiso p in usuario.Permiso)
                        {
                            db.SetParameterValue(cmdPermisos, "estado", p.Estado);
                            db.SetParameterValue(cmdPermisos, "idEmpleado", usuario.IdEmpleado);
                            db.SetParameterValue(cmdPermisos, "idFormulario", p.IdFormulario);
                            db.SetParameterValue(cmdPermisos, "tipoPermiso", p.TipoPermiso);
                            db.ExecuteNonQuery(cmdPermisos, transaction);
                        }

                        transaction.Commit();
                    }
                    catch (Exception ex)
                    {
                        transaction.Rollback();
                        throw ex;
                    }
                }
            }
        }

        public void EditarUsuario(Usuario usuario)
        {
            using (DbConnection conection = db.CreateConnection())
            {
                conection.Open();
                using (DbTransaction transaction = conection.BeginTransaction())
                {
                    try
                    {
                        DbCommand cmdUsuario = db.GetStoredProcCommand("UpdateUsuario");

                        db.AddInParameter(cmdUsuario, "esAdministrador", DbType.Boolean, usuario.EsAdministrador);
                        db.AddInParameter(cmdUsuario, "fechaRegistro", DbType.DateTime, usuario.FechaRegistro);
                        db.AddInParameter(cmdUsuario, "idEmpleado", DbType.Int16, usuario.IdEmpleado);
                        db.AddInParameter(cmdUsuario, "password", DbType.String, usuario.Password);
                        db.AddInParameter(cmdUsuario, "username", DbType.String, usuario.Username);
                        db.ExecuteNonQuery(cmdUsuario, transaction);

                        DbCommand cmdPermisos = db.GetStoredProcCommand("InsertPermiso");
                        db.AddInParameter(cmdPermisos, "estado", DbType.Boolean);
                        db.AddInParameter(cmdPermisos, "idEmpleado", DbType.Int16);
                        db.AddInParameter(cmdPermisos, "idFormulario", DbType.Byte);
                        db.AddInParameter(cmdPermisos, "tipoPermiso", DbType.Byte);

                        foreach (Permiso p in usuario.Permiso)
                        {
                            db.SetParameterValue(cmdPermisos, "estado", p.Estado);
                            db.SetParameterValue(cmdPermisos, "idEmpleado", usuario.IdEmpleado);
                            db.SetParameterValue(cmdPermisos, "idFormulario", p.IdFormulario);
                            db.SetParameterValue(cmdPermisos, "tipoPermiso", p.TipoPermiso);
                            db.ExecuteNonQuery(cmdPermisos, transaction);
                        }

                        transaction.Commit();
                    }
                    catch (Exception ex)
                    {
                        transaction.Rollback();
                        throw ex;
                    }
                }
            }
        }

        public void EliminarUsuario(short idEmpleado)
        {
            DbCommand command = db.GetStoredProcCommand("DeleteUsuario");
            db.AddInParameter(command, "idEmpleado", DbType.Int16, idEmpleado);
            db.ExecuteNonQuery(command);
        }

        #endregion

        #region Permisos

        public List<Permiso> ListarPermisos(short idEmpleado)
        {
            List<Permiso> permisos = new List<Permiso>();

            DbCommand command = db.GetStoredProcCommand("GetPermisosByUsuario");
            db.AddInParameter(command, "idEmplerado", DbType.Int32, idEmpleado);

            using (IDataReader dr = db.ExecuteReader(command))
            {
                while (dr.Read())
                {
                    permisos.Add(new Permiso
                    {
                        Estado = dr.GetBoolean(dr.GetOrdinal("Estado")),
                        IdEmpleado = dr.GetInt16(dr.GetOrdinal("IdEmpleado")),
                        IdFormulario = dr.GetByte(dr.GetOrdinal("IdFormulario")),
                        TipoPermiso = dr.GetByte(dr.GetOrdinal("TipoPermiso"))
                    });
                }
            }
            return permisos;
        }

        public List<Permiso> ListarPermisosPorUsuarioAndFormulario(short idEmpleado, byte idFormulario)
        {
            List<Permiso> permisos = new List<Permiso>();

            DbCommand command = db.GetStoredProcCommand("GetPermisosByUsuarioAndFormulario");
            db.AddInParameter(command, "idEmplerado", DbType.Int32, idEmpleado);
            db.AddInParameter(command, "idFormulario", DbType.Int32, idFormulario);

            using (IDataReader dr = db.ExecuteReader(command))
            {
                while (dr.Read())
                {
                    permisos.Add(new Permiso
                    {
                        Estado = dr.GetBoolean(dr.GetOrdinal("Estado")),
                        IdEmpleado = dr.GetInt16(dr.GetOrdinal("IdEmpleado")),
                        IdFormulario = dr.GetByte(dr.GetOrdinal("IdFormulario")),
                        TipoPermiso = dr.GetByte(dr.GetOrdinal("TipoPermiso"))
                    });
                }
            }
            return permisos;
        }

        public List<Permiso> ListarPermisosPorUsuarioMenu(short idEmpleado, byte idMenu)
        {
            List<Permiso> permisos = new List<Permiso>();

            DbCommand command = db.GetStoredProcCommand("GetPermisosByUsuarioAndMenu");
            db.AddInParameter(command, "idEmplerado", DbType.Int32, idEmpleado);
            db.AddInParameter(command, "idMenu", DbType.Int32, idMenu);

            using (IDataReader dr = db.ExecuteReader(command))
            {
                while (dr.Read())
                {
                    permisos.Add(new Permiso
                    {
                        Estado = dr.GetBoolean(dr.GetOrdinal("Estado")),
                        IdEmpleado = dr.GetInt16(dr.GetOrdinal("IdEmpleado")),
                        IdFormulario = dr.GetByte(dr.GetOrdinal("IdFormulario")),
                        TipoPermiso = dr.GetByte(dr.GetOrdinal("TipoPermiso"))
                    });
                }
            }
            return permisos;
        }

        public List<Permiso> ListarPermisosPorUsuarioMenuConAcceso(short idEmpleado, byte idMenu)
        {
            List<Permiso> permisos = new List<Permiso>();

            DbCommand command = db.GetStoredProcCommand("GetPermisosByUsuarioAndMenuWithAcceso");
            db.AddInParameter(command, "idEmplerado", DbType.Int32, idEmpleado);
            db.AddInParameter(command, "idMenu", DbType.Int32, idMenu);

            using (IDataReader dr = db.ExecuteReader(command))
            {
                while (dr.Read())
                {
                    permisos.Add(new Permiso
                    {
                        Estado = dr.GetBoolean(dr.GetOrdinal("Estado")),
                        IdEmpleado = dr.GetInt16(dr.GetOrdinal("IdEmpleado")),
                        IdFormulario = dr.GetByte(dr.GetOrdinal("IdFormulario")),
                        TipoPermiso = dr.GetByte(dr.GetOrdinal("TipoPermiso"))
                    });
                }
            }
            return permisos;
        }

        #endregion
    }
}
